﻿using System.Diagnostics;
using System.Text;

namespace KinonekoSoftware.Extensions.Strings.SearchModels.TrieTree
{
    internal class TrieTreeGlossaryProviderEnumerator
    {
        public static IEnumerable<string> GetArray(ITrieTreeGlossaryProviderRoot trieTree)
        {
            var nodeStack  = new Stack<Node>();
            var indexStack = new Stack<IEnumerator<KeyValuePair<char, Node>>>();
            var results    = new List<string>();

            var root  = trieTree.Root;
            var count = trieTree.Count;
            var sb    = new StringBuilder();
            
            //
            //
            nodeStack.Push(root);
            indexStack.Push(root.Children.GetEnumerator());

            while (nodeStack.Count != 0 && indexStack.Count != 0)
            {
                var node     = nodeStack.Peek();
                var iterator = indexStack.Peek();
                
                if (node.HasChildren)
                {
                    

                    if (iterator.MoveNext())
                    {
                        //
                        // push stack
                        var current = iterator.Current;
                        nodeStack.Push(current.Value);
                        indexStack.Push(current.Value.Children.GetEnumerator());
                    }
                    else
                    {
                        if (node.IsWordEnd)
                        {
                            foreach (var ch in nodeStack.Where(x => !x.IsRoot).Select(x => x.Value).Reverse())
                            {
                                sb.Append(ch);
                            }
                    
                            results.Add(sb.ToString());
                            sb.Clear();
                        }
                        
                        //
                        // pop
                        nodeStack.Pop();
                        indexStack.Pop();
                    }
                }
                else
                {
                    if (node.IsWordEnd)
                    {
                        foreach (var ch in nodeStack.Where(x => !x.IsRoot).Select(x => x.Value).Reverse())
                        {
                            sb.Append(ch);
                        }
                    
                        results.Add(sb.ToString());
                        sb.Clear();
                    }
                    
                    //
                    // pop
                    nodeStack.Pop();
                    indexStack.Pop();
                }
                
            }


            Debug.Assert(count == results.Count);
            
            return results;
        }
        
    }
}